package cfgloader

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"fmt"
	"os"
	"strings"
	"time"
)

// ListenFunc 配置文件更改监听回调函数
type ListenFunc func(string)

// Listener 配置文件更改监听回调接口
type Listener interface {
	listen(inifile string)
}

func (f ListenFunc) listen(inifile string) {
	f(inifile)
}

func hashCalc(filename string) (string, error) {
	h := sha1.New()
	fd, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer fd.Close()
	reader := bufio.NewReader(fd)
	buf := make([]byte, 1024)
	for {
		len, err := reader.Read(buf)
		if err != nil || len == 0 {
			break
		}
		h.Write(buf[0:len])
	}
	return fmt.Sprintf("%x", h.Sum(nil)), nil
}

func readFile(filename string) (string, error) {
	fd, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer fd.Close()
	reader := bufio.NewReader(fd)
	scanner := bufio.NewScanner(reader)
	var buffer bytes.Buffer

	for scanner.Scan() {
		buffer.WriteString(scanner.Text())
		buffer.WriteString("\n")
	}

	return buffer.String(), nil
}

// Watch 监听 ini 文件更改
func Watch(filename string, listener Listener) (*configuration, error) {
	hash, err := hashCalc(filename)
	if err != nil {
		return nil, err
	}

	go func() {
		lastHash := hash
		for {
			time.Sleep(100)
			currentHash, err := hashCalc(filename)
			if err != nil {
				fmt.Println(err)
				return
			}
			if strings.Compare(currentHash, lastHash) != 0 {
				lastHash = currentHash
				file, err := readFile(filename)
				if err != nil {
					fmt.Println(err)
					continue
				}
				listener.listen(file)
			}
		}
	}()

	return LoadConfigFromFile(filename)
}
